home *** CD-ROM | disk | FTP | other *** search
- Date: Mon, 1 Jun 1992 20:00:07 GMT
- Subject: Mail auditing + more package
- From: Martin Streicher <strike@convex.COM>
-
- I am changing jobs, so this will be the final release of my audit
- package until I get a new UNIX account established. There are
- several little bugs fixed in this release that should fix
- lots of parsing problems - other than that, this package seems very solid
- and I have gotten good feedback on the usefulness of the package.
-
- Enjoy...
-
- The audit.pl package.
- =====================
-
- What this package does:
- =======================
- This package provides routines that parse an incoming mail message, divide
- it into a header and the body of the message and further decompose
- the mail header into its fields. The routines set variables that you
- can query and parse in your own PERL script to determine what to do with
- the incoming mail message.
-
- To use the package, insert the following two PERL instructions to the very
- TOP of your PERL script:
-
- require '/gmaster/home/strike/work/perl/deliver/audit.pl' ||
- die "deliver: cannot include audit.pl: $@";
-
- &initialize();
-
-
- Variables that &initialize() sets:
- ---------------------------------
- The routine &initialize() reads the incoming mail message and sets
- the following variables:
-
- $sender This is the sender shown on the "From " line.
-
- %headers An associative array containing the lines in the mail
- header. $header{'Subject'} contains the Subject: line;
- $header{'Date'} contains Date:, etc.
-
- If the To: or Cc: line appeared more than once in the header,
- those lines are concatenated together into a single
- comma-separated list of names. Other header lines that
- appear twice are clobbered.
-
- There are also many variables and arrays set for your convenience if you
- dont want to parse the entries of %headers yourself.
-
- $subject The Subject: line.
-
- $precedence The Precedence: line.
-
- $friendly The friendly (human) name of the sender
- (e.g., Martin Streicher)
-
- $address The email address of the sender
- (e.g., strike@pixel.convex.com)
-
- $from The login name of the sender with all addressing stripped. For
- example, if $address was strike@pixel.convex.com, $from
- is strike.
-
- $organization The name of the sender's organization. This is derived from
- $address; for example strike@pixel.convex.com yields convex;
- wizard!jim@uunet.uu.net yields wizard; jane@mach.site.co.uk
- yields site.
-
- @to The list of names on the To: line(s). Note that the
- name listed on the Apparently-To: line also appears in @to.
-
- @cc The list of names on the Cc: line(s).
-
- @received The list of received headers in the mail message that
- show the path the message traveled to be delivered.
-
-
- Routines that audit.pl provides:
- --------------------------------
- The package offers some canned routines for handling the incoming
- mail message:
-
- &deliver() Deliver the incoming mail message. &deliver() appends
- the incoming mail message to the end of your UNIX mail
- drop /usr/spool/mail/<user>, where <user> is the name
- specified in the .forward file.
-
- &vacation() Reply automatically to the sender if you have a vacation
- message in $HOME/.vacation.msg. If you do not have this
- file, this routine does absolutely nothing. If you have
- a .vacation.msg file, &vacation sends the sender of the
- message an automatic reply containing that file.
-
- This routine also records who you sent
- vacation mail to; it will not send duplicate vacation messages
- to the same person. If you change your vacation message, the
- list is zeroed. The list of people you sent vacation mail to
- is kept in $HOME/.vacation.log.
-
- Some notes about &vacation():
- - It will send you vacation mail. This is useful
- to test your vacation message out.
-
- - It will not send vacation mail to anyone named
- root, mailer-daemon, postmaster, daemon or mailer.
- This are not considered to be real users.
-
- - It will not respond to mail that is labelled
- with precendence bulk or junk.
-
- &file_from() or
- &file_from($dir)
- This routine files the incoming mail message
- in a hierarchy of mail folders. The top-level of the
- hierarchy is specified in $dir; by default (if no
- directory is specified) it is $HOME/log. The next level
- of the hierachy is sorted by $organization; below this level
- mail is sorted by the sender's login name.
-
- For example, say you receive a message from
- strike@pixel.convex.com; if you call &file_from(),
- the corresponsing mail message will be filed into a mail
- folder called $HOME/log/convex/strike. All mail sent to you
- by strike@pixel.convex.com would be filed in this mail folder.
-
- You can &file_from to file all correspondence for future
- reference.
-
- &openpipe($command)
- You can also use your own commands (scripts/programs)
- to process an incoming mail message. &openpipe($command)
- opens a PERL pipe to $command and pipes the mail message
- to that command.
-
- You can use none, one or all of these routines. You can also repeat
- and combine all of these functions to do more than one thing with a piece of
- incoming mail (you probably only want to &deliver() the message once though).
-
- For example, say you get a message from strike@pixel.convex.com. You want
- to file the message away for auditing purposes, save the mail message in your
- mail drop and send some vacation mail if you are gone. Use the &file_from(),
- &deliver() and &vacation() functions to do all of these things to one message.
-
- WARNING: IF YOU EXIT FROM THE PERL SCRIPT WITHOUT DOING SOMETHING
- WITH THE MAIL MESSAGE, IT IS LOST FOREVER.
-
- Actually, exiting the PERL script can be an effective way of dropping
- unwanted mail messages. See the example below.
-
-
- Other convenience functions for MH users:
- -----------------------------------------
- If you use MH, other convenience routines are provided to
- pipe the incoming mail message to rcvstore, rcvdist and/or rcvtty.
- There is also a special refile routine to file incoming mail messages
- in folders according to the sender's organization and login.
-
- To access the MH functions, add the following line to the TOP of your script:
-
- require '/gmaster/home/strike/work/perl/deliver/mh.pl' ||
- die "deliver: cannot include mh.pl: $@";
-
- This file provides the following functions:
-
- &rcvstore($folder)
- Pipe the incoming mail message to rcvstore; the $folder
- argument is the name of the folder to store the message
- into.
-
- &rcvtty() Pipe the incoming mail message to rcvtty. rcvtty
- is MH's equivalent to biff and its output can be tailored
- exactly like you can customize scan or inc.
-
- &rcvdist($names)
- Pipe the incoming mail message to rcvdist. $names
- is a blank separated list of names to send the
- message to. You can use the &ali() command (see below)
- to expand MH aliases.
-
- &ali($alias) Expand the MH alias name in $alias to the list
- of addresses it stands for. Unlink all the other routines,
- this routine returns an array of names, where
- each element is an addressee on the alias.
-
- &refile_from() or
- &refile_from($dir)
- File a copy of the incoming mail message into a hierarchy of
- MH folders. The top-level directory is "log" by default unless
- you specify another folder (all this below you Mailpath folder,
- of course). The next level is sorted by organization name
- and the level below that is sorted by sender's login name.
-
-
-
- Writing a PERL mail auditing script:
- ====================================
- The best way to show what all this can do is with a specific example. Here
- is my script (with comments!):
-
- ------ script starts here -------
- #! /usr/local/bin/perl
-
- require '/gmaster/home/strike/work/perl/deliver/audit.pl' ||
- die "deliver: cannot include audit.pl: $@";
-
- require '/gmaster/home/strike/work/perl/deliver/mh.pl' ||
- die "deliver: cannot include mh.pl: $@";
-
- &initialize();
-
-
- # -----
- # My mail processing starts here
- #
-
- # If this message came from the MAILER, deliver it to me directly
- # and do nothing else.
- #
- ($from =~ /MAILER/) && do { &deliver(); exit; };
-
- # If this message is sent to xpixel (either To or Cc, deliver
- # the messsage to me and exit.
- #
- (grep(/^xpixel/, @to, @cc)) && do { &deliver(); exit; };
-
- # If the message is from a place called "lupine", this
- # is really NCD.
- #
- $organization = "ncd" if ($organization eq "lupine");
-
- # If the sender's name is in the password file, the organization
- # is CONVEX.
- #
- $organization = "convex" if ($logname = (getpwnam($from))[0]);
-
- # If I am specifically named on the To or Cc line, do the default.
- # The routine &default is below: it delivers the message, refiles
- # it in an MH folder, sends vacation mail if I am gone, and
- # biffs me if I am logged in somewhere.
- #
- (grep(/^strike/, @to, @cc)) && do {
- &default();
- exit;
- };
-
- # If the mail message went to x<hostname> where hostname
- # is in our /etc/hosts, trash the message (JUST EXIT TO DROP
- # THE MESSAGE)
- #
- exit if (grep((/^x(.*)/ && (@n = gethostbyname($1))), @to, @cc));
-
- # Throw away anything to anyone or any alias named avs-updates
- #
- exit if (grep(($_ eq "avs-updates"), @to));
-
- # Throw away junk mail from AVS, Inc.
- #
- if ($organization eq "avs") {
- exit if ($subject =~ /^(Opened|Assigned) to/);
- exit if ($subject =~ /^(Edited|Fixed|Killed) by/);
- };
-
-
- # If the mail message went to an X Consortium alias,
- # deliver it to me if it is advisory board mail. Otherwise,
- # refile it into an archive and redistribute it to anyone at CONVEX
- # that subscribes to it through me.
- #
- $xcons = 0;
- @consortium = (
- '/^advisory/', '/^blend/', '/^bug-trackers/',
- '/^color/', '/^fix-trackers/', '/^fontwork/',
- '/^imagework/', '/^xlib/', '/intrinsics/',
- '/^mltalk/', '/^pex-si/', '/^pex-spec/',
- '/^protocol/', '/^security/', '/^shape/',
- '/^trackers/', '/^transport/', '/^wmtalk/',
- '/^xbuffer/', '/^xc/', '/^xinput/',
- '/^xtest/', '/^consortium/', '/^serialwork/',
- '/^xie_/', '/^mtserver/'
- );
-
- foreach $list (@consortium) {
- for (grep(eval $list, @to, @cc)) {
- &deliver() if ($_ =~ "^advisory");
- $xcons++;
- &rcvstore("XConsortium/$_");
- @dist = &ali("XConsortium-$_");
- &rcvdist(join(' ', @dist)) if ((@dist));
- };
- };
- exit if $xcons;
-
-
- # this mail was not sent to me directly, so dont answer with vacation mail,
- #
- &deliver();
- &rcvtty();
-
- # All done!
- #
- exit;
-
-
- # =====
- # Subroutine default
- # defaults specifies what to do when I want to accept a piece
- # of mail. It is a convenience.
- sub default {
-
- &deliver();
- &vacation();
- &rcvtty();
- &refile_from();
- }
-
- ------ script ends ----------
-
-
- Testing
- ========
- If you want to test your PERL script, put the following in your .forward file:
-
- <login>, "| <homedir>/<script> <login>
-
- where <login> is your UNIX login, <homedir> is the absolute path name
- to your home directory and <script> is the name of your PERL mail
- auditing script. If you put this in .forward, incoming mail messages
- will be directly sent to your mail drop AND will be piped through your
- PERL script. You may get duplicates of some mail, but this is the best
- way to see what your script is doing.
-
- Once you are satisifed that your script works, simply replace your
- .forward file with:
-
- "| <homedir>/<script> <login>
-
- Please note that if your script has syntax errors, the mailer will
- not drop your incoming mail; instead it will send you a the incoming
- mail message and a note indicating that an unknown mailer error occurred.
-
- Another way to test your script:
- --------------------------------
- You can also test your script by piping a UNIX mail folder (like your
- mail drop) directly into your script. For example, say you are having
- problems with mail from a certain sender or network alias; to debug your
- script, copy your incoming mail box in /usr/spool/mail to a local file
- and then pipe it to your script ala:
-
- cat mail | perl -d ~/.audit
-
- You can then step through the script and see how the mail message
- is being parsed. You can add breakpoints, print statements, etc. and see
- the script operate on the mail. If you use &vacation() or &file_from(),
- you can watch those routines operate as well. The mail message is processed
- as if it came directly to your script courtesy of the delivery system.
-